define([
  'esri/layers/GraphicsLayer',
  'esri/graphic',
  'esri/symbols/SimpleMarkerSymbol',
  'esri/symbols/SimpleFillSymbol',
  'esri/symbols/TextSymbol',
  'esri/symbols/Font',
  'esri/Color',
  'Utils/SegmentedColor',
  'dojo/_base/declare'
], function(
  GraphicsLayer,
  Graphic,
  SimpleMarkerSymbol,
  SimpleFillSymbol,
  TextSymbol,
  Font,
  Color,
  SegmentedColor,
  declare
) {
  'use strict';

  /**
   * 一天4次，00Z，06Z，12Z，18Z   （四川区域模式） 一天2次，00Z，12Z （欧洲中心）
   */
  return declare(null, {
    cellCout: 150, //格子数目
    suiningPolygon: null,
    suiningExtentPolygon: null,
    spotGraphicLayer: null, //色斑图
    layerOpacity: 0.5, // 图层透明度
    valueGraphicLayer: null, //数值标注图
    pointsExtentArr: null, //遂宁市 extent 内的点数据
    pointsArr: null, //遂宁市范围内的点数据
    lngArr: [],
    latArr: [],
    valueExtentArr: [], //遂宁市 extent 内的数值
    valueArr: [], //遂宁市范围内的点数值
    period: 16, //色段数目
    segmentedColorObj: null, //色标分段
    limitValue: 0.005, // 筛选值
    constructor: function() {
      //色斑图
      this.spotGraphicLayer = new GraphicsLayer();
      this.spotGraphicLayer.setOpacity(this.layerOpacity);
      //数值标注图
      this.valueGraphicLayer = new GraphicsLayer();

      // 获取遂宁范围
      var suiningwkt =
        'POLYGON((105.61447 30.97882,105.66577 30.92742,105.72907 30.90762,105.73077 30.86712,105.79307 30.80192,105.77657 30.78382,105.79017 30.71172,105.83467 30.58662,105.87287 30.56022,105.85687 30.51582,105.88107 30.47582,105.92017 30.47012,105.93007 30.52082,105.96747 30.48052,105.95727 30.43052,105.98397 30.41632,105.99727 30.37912,105.93987 30.37482,105.84257 30.41392,105.81657 30.44022,105.76827 30.40672,105.74987 30.36452,105.70547 30.30262,105.72027 30.25742,105.66987 30.25552,105.61927 30.27662,105.61677 30.23702,105.63897 30.18922,105.57657 30.17632,105.55617 30.18552,105.51717 30.20492,105.46967 30.25112,105.42097 30.26322,105.40347 30.29282,105.36717 30.27882,105.35387 30.31092,105.25517 30.28272,105.11687 30.34872,105.08777 30.40352,105.08777 30.46412,105.05697 30.52342,105.06437 30.53802,105.08267 30.55322,105.16497 30.67822,105.16637 30.70842,105.26847 30.75442,105.25707 30.82782,105.22627 30.87832,105.19297 30.89372,105.19337 30.98232,105.17147 31.03682,105.22637 31.10572,105.28477 31.10342,105.37887 31.15462,105.38597 31.11422,105.41317 31.07392,105.50707 31.02952,105.53287 31.02842,105.59147 30.97592,105.61447 30.97882))';
      var feature = new ol.format.WKT().readFeature(suiningwkt);
      var json = new ol.format.GeoJSON().writeFeature(feature);
      this.suiningPolygon = turf.polygon(JSON.parse(json).geometry.coordinates);

      // 加载遂宁范围
      // var polygon = new esri.geometry.Polygon(JSON.parse(json).geometry.coordinates);
      // var psymbol = new SimpleFillSymbol();
      // var pgraphic = new Graphic(polygon, psymbol);
      // this.spotGraphicLayer.add(pgraphic);
      // console.log(polygon);

      var suiningExtentwkt = 'POLYGON((104 29,107 29,107 32,104 32,104 29))';
      var featureExtent = new ol.format.WKT().readFeature(suiningExtentwkt);
      var jsonExtent = new ol.format.GeoJSON().writeFeature(featureExtent);
      this.suiningExtentPolygon = turf.polygon(JSON.parse(jsonExtent).geometry.coordinates);
    },

    //设置数据源
    setDataPointObjArr: function(dataPointObjArr) {
      var ptArr = dataPointObjArr.pointsArr;
      var resultArr = [];
      var resultExtentArr = [];
      for (var i = 0; i < ptArr.length; i++) {
        // 收集遂宁 extent 范围内的点
        var pointExtent = turf.point([ptArr[i].x, ptArr[i].y]);
        var resultExtent = turf.booleanContains(this.suiningExtentPolygon, pointExtent);
        if (resultExtent) {
          resultExtentArr.push(ptArr[i]);
        }
        //收集遂宁市实际范围内的点
        var point = turf.point([ptArr[i].x, ptArr[i].y]);
        var result = turf.booleanContains(this.suiningPolygon, point);
        if (result) {
          resultArr.push(ptArr[i]);
        }
      }
      this.pointsArr = resultArr;
      this.pointsExtentArr = resultExtentArr;
      this.interpolation();
    },
    // 添加图层到地图
    getRainfallLayers: function() {
      // 添加点数据到数值图层
      var simpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 3);

      var font = new Font('10px', Font.STYLE_NORMAL, Font.VARIANT_NORMAL, Font.WEIGHT_BOLDER);

      for (var i = 0; i < this.pointsExtentArr.length; i++) {
        var pointArc = this.pointsExtentArr[i];
        var point = turf.point([pointArc.x, pointArc.y]);
        // 判断点是否在遂宁市区内
        var result = turf.booleanContains(this.suiningPolygon, point);
        if (result) {
          // 去掉值为 0 的数据
          if (this.pointsExtentArr[i].value < this.limitValue) {
            continue;
          }
          var textSymbol = new TextSymbol(
            this.pointsExtentArr[i].value.toFixed(3) + '',
            font,
            new Color([0, 0, 0])
          );
          textSymbol.setOffset(0, 5);
          var graphic1 = new Graphic(pointArc, simpleMarkerSymbol);
          var graphic2 = new Graphic(pointArc, textSymbol);
          this.valueGraphicLayer.add(graphic1);
          this.valueGraphicLayer.add(graphic2);

          //隐藏数值
          this.setValueLayerVisible(false);
        }
      }

      return [this.spotGraphicLayer, this.valueGraphicLayer];
    },
    // 设置色斑图图层是否可见
    setSpotLayerVisible: function(isVisible) {
      this.spotGraphicLayer.setVisibility(isVisible);
    },
    //设置数值标注图层是否可见
    setValueLayerVisible: function(isVisible) {
      this.valueGraphicLayer.setVisibility(isVisible);
    },

    // 插值
    interpolation: function() {
      this.lngArr = [];
      this.latArr = [];
      this.valueExtentArr = []; //数值
      this.valueArr = [];

      for (var i = 0; i < this.pointsExtentArr.length; i++) {
        // console.log(this.pointsExtentArr[i]);
        this.lngArr.push(this.pointsExtentArr[i].x);
        this.latArr.push(this.pointsExtentArr[i].y);
        this.valueExtentArr.push(this.pointsExtentArr[i].value);
      }

      for (var i = 0; i < this.pointsArr.length; i++) {
        this.valueArr.push(this.pointsArr[i].value);
      }

      if (this.pointsExtentArr.length == 0) return;
      // 创建网格 并插值
      this.createGrid();
    },

    // 创建格网并插入kriging值
    createGrid: function() {
      //获取 lngArr latArr valueExtentArr 最大最小值
      var rangeminX = this.getMin(this.lngArr);
      var rangemaxX = this.getMax(this.lngArr);
      var rangeminY = this.getMin(this.latArr);
      var rangemaxY = this.getMax(this.latArr);
      //数据最小值
      var rangeminValue = this.getMin(this.valueArr);
      //数据最大值
      var rangemaxValue = this.getMax(this.valueArr);
      // 比较最大值和筛选值
      if (rangeminValue < this.limitValue) rangeminValue = this.limitValue;
      // 比较最大值和最小值
      if (rangeminValue > rangemaxValue) rangeminValue = rangemaxValue;

      //引入色标分段
      this.segmentedColorObj = new SegmentedColor(rangeminValue, rangemaxValue, this.period);
      this.segmentedColorObj.createSegmentedColor();
      this.segmentedColorObj.createSegmentedColorValue();

      // 获取范围值
      var xl = rangemaxX - rangeminX; //经度跨度
      var yl = rangemaxY - rangeminY; //纬度跨度
      var gridX = xl / this.cellCout;
      var gridY = yl / this.cellCout;
      var lggridx = (rangemaxX - rangeminX) / this.cellCout;
      var lggridy = (rangemaxY - rangeminY) / this.cellCout;

      // 基于给定点建立克立金插值的范围
      var gX = rangeminX;
      var gridPoint = [];
      var krigingValue = [];

      var variogram = this.getKringVariogram();
      for (var i = 0; i < this.cellCout; i++) {
        gX = gX + gridX;
        var gY = rangeminY;
        for (var j = 0; j < this.cellCout; j++) {
          gY = gY + gridY;
          krigingValue[krigingValue.length] = this.getKring(gX, gY, variogram);
          gridPoint[gridPoint.length] = [gX, gY];
        }
      }

      var zi;
      // 根据插值创建色块Polygon
      for (var i = 0; i < this.cellCout * this.cellCout; i++) {
        var point = turf.point([gridPoint[i][0], gridPoint[i][1]]);
        var result = turf.booleanContains(this.suiningPolygon, point);

        if (result) {
          zi = krigingValue[i];
          // 筛选显示的值
          if (zi >= this.limitValue) {
            this.createPolygon(gridPoint[i][0], gridPoint[i][1], zi, lggridx, lggridy);
          }
        }
      }
    },

    // 初始化kring,获取 变差函数
    getKringVariogram: function() {
      var trans = this.lngLatToXY(this.lngArr, this.latArr);
      var x = trans[0];
      var y = trans[1];
      var value = this.valueExtentArr;

      var model = 'spherical';
      var sigma2 = 0;
      var alpha = this.cellCout;
      var variogram = kriging.train(value, x, y, model, sigma2, alpha);
      return variogram;
    },

    // 基于多边形的位置，得到克里金值。
    getKring: function(xk, yk, variogram) {
      var xnew, ynew /* Pair of new coordinates to predict */;
      var arr = esri.geometry.lngLatToXY(xk, yk);
      var tpredicted = kriging.predict(arr[0], arr[1], variogram);

      return tpredicted;
    },

    // 将给定的纬度和经度值转换为Web墨卡托。
    lngLatToXY: function(lngArr, latArr) {
      var xArr = [];
      var yArr = [];
      for (var i = 0; i < lngArr.length; i++) {
        var arr = esri.geometry.lngLatToXY(lngArr[i], latArr[i]);
        if (arr.length == 2) {
          xArr[i] = arr[0];
          yArr[i] = arr[1];
        }
      }
      return [xArr, yArr];
    },

    createPolygon: function(xi, yi, zi, lggridx, lggridy) {
      var polygonJson = {
        rings: [[[xi - lggridx, yi - lggridy], [xi, yi - lggridy], [xi, yi], [xi - lggridx, yi]]],
        spatialReference: {
          wkid: 4326
        }
      };
      var polygon = new esri.geometry.Polygon(polygonJson);
      var simpleFillSymbol = new SimpleFillSymbol();
      simpleFillSymbol.setOutline(null);

      var colorArr = this.segmentedColorObj.getGradientColorArr();
      var colorValueArr = this.segmentedColorObj.getGradientColorValueArr();

      var index = this.searchIndex(colorValueArr, zi);
      if (index != -1 && index < colorArr.length) {
        simpleFillSymbol.setColor(new esri.Color(colorArr[index]));
      }

      var graphic = new Graphic(polygon, simpleFillSymbol);
      this.spotGraphicLayer.add(graphic);
    },

    getMin: function(arr) {
      return Math.min.apply(null, arr);
    },
    getMax: function(arr) {
      return Math.max.apply(null, arr);
    },
    // 移除图层
    removeRainfallLayer: function(map) {
      map.removeLayer(this.spotGraphicLayer);
      map.removeLayer(this.valueGraphicLayer);
    },

    // 二分法查找，返回索引
    searchIndex: function(arr, key) {
      for (var i = 0; i < arr.length; i++) {
        if (i + 1 < arr.length) {
          if (key >= arr[i] && key <= arr[i + 1]) {
            return i;
          }
        }
      }
      return 0;
    },
    //解决图例显示不出来问题
    showLegend: function() {
      this.segmentedColorObj.createSegmentedColor();
    }
  });
});
